package mybatis;

import org.apache.commons.collections4.CollectionUtils;
import org.mybatis.generator.api.ConnectionFactory;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.JavaTypeResolver;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.config.TableConfiguration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.JDBCConnectionFactory;
import org.mybatis.generator.internal.ObjectFactory;
import org.mybatis.generator.internal.db.DatabaseIntrospector;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.apache.ibatis.io.Resources.getResourceAsStream;

/**
 * @author zsh
 * @version V1.0
 * @since 1.0 2020/6/22 9:25
 */
public class DataBaseDiff {

    private static final String SQL = "SELECT TABLE_NAME FROM USER_TABLES";

    public static void main(String[] args) throws Exception {
        List<String> devTableList = new ArrayList<>();
        List<String> nwTableList = new ArrayList<>();


        List<String> warnings = new ArrayList<>();
        boolean overwrite = true;
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(getResourceAsStream("generatorConfig-work.xml"));
        Context oracle = config.getContext("oracle");
        Connection connection = getConnection(oracle);
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(SQL);
        while (resultSet.next()) {
            devTableList.add(resultSet.getString(1));
        }

        oracle.getJdbcConnectionConfiguration().setConnectionURL("jdbc:oracle:thin:@191.168.0.33:1521:xalms");
        oracle.getJdbcConnectionConfiguration().setUserId("xpims_trd_nw");
        connection = getConnection(oracle);
        statement = connection.createStatement();
        resultSet = statement.executeQuery(SQL);
        while (resultSet.next()) {
            nwTableList.add(resultSet.getString(1));
        }
        System.out.println("标准库表数量: " + devTableList.size() + "   南网库表数量: " + nwTableList.size());
        Collection<String> moreTables = CollectionUtils.subtract(devTableList, nwTableList);
        Collection<String> intersection = CollectionUtils.intersection(devTableList, nwTableList);
        //Collection<String> intersection = Collections.singleton("TTRD_AUTH_USER");
        System.out.println("标准库多的表的数量:" + moreTables.size());
        System.out.println("都有表的数量:" + intersection.size());
        PrintWriter writer = new PrintWriter("/Users/zsh/idea-projects/learn/src/main/resources/test.txt");
        for (String moreTable : moreTables) {
            writer.println(moreTable);
        }


        JavaTypeResolver javaTypeResolver = ObjectFactory
                .createJavaTypeResolver(oracle, warnings);
        DatabaseIntrospector databaseIntrospector = new DatabaseIntrospector(
                oracle, connection.getMetaData(), javaTypeResolver, warnings);

        TableConfiguration configuration = new TableConfiguration(oracle);
        List<IntrospectedTable> nwTableInfos = new ArrayList<>();
        for (String tbl : intersection) {
            configuration.setTableName(tbl);
            configuration.setSchema("XPIMS_TRD_NW");
            List<IntrospectedTable> introspectedTables = databaseIntrospector.introspectTables(configuration);
            nwTableInfos.addAll(introspectedTables.stream()
                    .filter(introspectedTable -> "TABLE".equals(introspectedTable.getTableType()))
                    .collect(Collectors.toList()));
        }


        oracle.getJdbcConnectionConfiguration().setConnectionURL("jdbc:oracle:thin:@191.168.0.62:1521:xpims");
        oracle.getJdbcConnectionConfiguration().setUserId("xpims_trd");
        connection = getConnection(oracle);
        databaseIntrospector = new DatabaseIntrospector(
                oracle, connection.getMetaData(), javaTypeResolver, warnings);
        List<IntrospectedTable> devTableInfos = new ArrayList<>();
        for (String tbl : intersection) {
            configuration.setTableName(tbl);
            configuration.setSchema("XPIMS_TRD");
            List<IntrospectedTable> introspectedTables = databaseIntrospector.introspectTables(configuration);
            devTableInfos.addAll(introspectedTables.stream()
                    .filter(introspectedTable -> "TABLE".equals(introspectedTable.getTableType()))
                    .collect(Collectors.toList()));
        }

        Map<String, IntrospectedTable> nwTableInfoMap = nwTableInfos.stream().collect(Collectors.toMap(introspectedTable -> introspectedTable.getFullyQualifiedTable().getIntrospectedTableName(),
                Function.identity()));
        compare(devTableInfos, nwTableInfoMap);

    }


    private static Connection getConnection(Context context) throws SQLException {
        ConnectionFactory connectionFactory;
        connectionFactory = new JDBCConnectionFactory(context.getJdbcConnectionConfiguration());
        return connectionFactory.getConnection();
    }

    private static void compare(List<IntrospectedTable> devTableInfos, Map<String, IntrospectedTable> nwTableInfoMap) {
        IntrospectedTable compareTable;
        List<IntrospectedColumn> devTableInfoAllColumns;
        List<IntrospectedColumn> compTableInfoAllColumns;
        Map<String, IntrospectedColumn> compMap;
        for (IntrospectedTable devTableInfo : devTableInfos) {
            compareTable = nwTableInfoMap.get(devTableInfo.getFullyQualifiedTable().getIntrospectedTableName());
            devTableInfoAllColumns = devTableInfo.getAllColumns();
            compTableInfoAllColumns = compareTable.getAllColumns();
            compMap = compTableInfoAllColumns.stream()
                    .collect(Collectors.toMap(IntrospectedColumn::getActualColumnName, Function.identity()));
            System.out.println("<<<<<========" + devTableInfo.getFullyQualifiedTable().getIntrospectedTableName() + "========>>>>>");
            IntrospectedColumn compColumn;
            for (IntrospectedColumn column : devTableInfoAllColumns) {
                compColumn = compMap.get(column.getActualColumnName());
                if (compColumn == null) {
                    System.out.println("新增字段:" + column.getActualColumnName());
                } else {
                    if (!Objects.equals(column.getJdbcTypeName(), compColumn.getJdbcTypeName()) ||
                            !Objects.equals(column.getLength(), compColumn.getLength()) ||
                            !Objects.equals(column.getScale(), compColumn.getScale())) {
                        System.out.println("类型不同:" + column.getActualColumnName() +
                                " " + column.getJdbcTypeName() + " " + column.getLength() + " " + column.getScale());
                    }
                }
            }
            System.out.println();

        }

    }


}
